package com.imooc.netty.websocket;

import io.netty.channel.Channel;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 会话管理-多端多设备
 * 用户id和channel的关联关系处理
 * @author liansen
 * @create 07-18-18:00
 */
public class UserChannelSession {

    /**
     * 用于多端同时接收消息，允许同一个账号在多个设备同时在线，比如手机和电脑和ipad都能同时收到消息
     * 一个客户端连接到netty服务器，就是一个channel，
     * 所以定义一个map,key是用户id,value是多个设备，也就是多个channel集合
     */
    private static final Map<String, List<Channel>> multiSession = new HashMap<>();

    /**
     * 用于记录用户id和客户端channel的长id的关联关系
     * key是channelId,value是用户id
     */
    private static final Map<String, String> userChannelIdRelation = new HashMap<>();


    public static void putUserChannelIdRelation(String channelId, String userId){
        userChannelIdRelation.put(channelId, userId);
    }

    //通过channelId找到对应的userId
    public static String getUserIdByChannelIdRelation(String channelId){
        return userChannelIdRelation.get(channelId);
    }

    public static void putMultiChannels(String userId, Channel channel){

        List<Channel> channels = getMultiChannels(userId);
        if(CollectionUtils.isEmpty(channels)){
            channels = new ArrayList<>();
        }
        channels.add(channel);
        multiSession.put(userId, channels);
    }

    public static List<Channel> getMultiChannels(String userId){
        return multiSession.get(userId);
    }

    //移除多余的会话channel
    public static void removeUselessChannels(String channelId, String userId){
        List<Channel> channels = getMultiChannels(userId);
        if(CollectionUtils.isEmpty(channels)){
            return;
        }
        //这里如果用增强for循环，因为操作对list进行了删除元素，会报并发修改异常
        //所以使用普通for循环，或者使用CopyOnWriteArrayList
        for(int i=0; i<channels.size(); i++){
            Channel channel = channels.get(i);
            if(channelId.equalsIgnoreCase(channel.id().asLongText())){
                channels.remove(channel);
            }
        }
        if(!CollectionUtils.isEmpty(channels)){
            multiSession.put(userId, channels);
        }else {
            multiSession.remove(userId);
        }
    }

    //获取发送者的其他设备channel
    public static List<Channel> getMyOtherChannels(String userId, String channelId){
        List<Channel> channels = getMultiChannels(userId);
        if(CollectionUtils.isEmpty(channels)){
            return null;
        }
        List<Channel> myOtherChannelList = new ArrayList<>();
        for(int i = 0; i < channels.size(); i++){
            Channel channel = channels.get(i);
            String id = channel.id().asLongText();
            if(!id.equalsIgnoreCase(channelId)){
                myOtherChannelList.add(channel);
            }
        }
        return myOtherChannelList;
    }


    //用于测试
    public static void outPutMulti(){

        System.out.println("---------------------");

        for(Map.Entry<String, List<Channel>> entry : multiSession.entrySet()){
            System.out.println("+++++++++");
            String key = entry.getKey();
            System.out.println("UserId: " + key);

            List<Channel> channels = entry.getValue();
            channels.forEach(channel -> System.out.println("channel: " + channel));
            System.out.println("+++++++++");
        }

        System.out.println("---------------------");
    }

    public static void test(){
        System.out.println("~~~~~~~~~~");

        for(Map.Entry<String, String> entry : userChannelIdRelation.entrySet()){
            String key = entry.getKey();
            System.out.println("key-channelId: " + key);

            String value = entry.getValue();
            System.out.println("value: " + value);
        }

        System.out.println("~~~~~~~~~~");
    }
}
